/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.i18n.manager;

import io.iec.edp.caf.i18n.I18nContext;
import io.iec.edp.caf.i18n.api.ResourceLocalizer;
import io.iec.edp.caf.i18n.spi.ResourceResolver;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 国际化资源服务接口实现类
 *
 * @author Vincent Man
 * @date 2023-03-27
 */
@Slf4j
public class ResourceLocalizerImpl implements ResourceLocalizer {

    //资源提供实例
    private static ResourceResolver resolver;

    static {
        ServiceLoader<ResourceResolver> resolvers = ServiceLoader.load(ResourceResolver.class);
        for (ResourceResolver r : resolvers) {
            if (resolver == null) {
                resolver = r;
                break;
            }
        }
    }

    @Override
    public String getString(String code, String resource, String pathId, String language) {
        String result = null;
        if (StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(resource)) {
            language = getLanguage(language);
            try {
                result = getStringByResourceID(code, resource, pathId, language);

                //log details
                if (log.isDebugEnabled()) {
                    log.debug("code = {}, resource = {}, pathId = {}, language = {}, result = {}.", code, resource, pathId, language, result);
                }
            } catch (Exception e) {
                throw new RuntimeException("Error getting string resource by [" + code + ", " + resource + ", " + pathId + ", " + language + "], Please check whether the resource file or code exists !", e);
            }
        }

        return result;
    }

    @Override
    public byte[] getBytes(String code, String resource, String pathId, String language) {
        byte[] result = null;
        if (StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(resource)) {
            language = getLanguage(language);
            try {
                result = getImageByResourceID(code, resource, pathId, language);
            } catch (Exception e) {
                throw new RuntimeException("Error getting bytes resource by [" + code + ", " + resource + ", " + pathId + ", " + language + "], Please check whether the resource file or code exists !", e);
            }
        }

        return result;
    }

    @Override
    public Image getImage(String code, String resource, String pathId, String language) {
        Image result = null;
        try {
            byte[] results = getBytes(code, resource, pathId, language);
            if (results != null) {
                String base64String = new String(results, StandardCharsets.UTF_8);
                int index;
                if ((index = base64String.indexOf("base64,")) > -1) {
                    base64String = base64String.substring(index + 7);
                }
                byte[] bytes = Base64.getDecoder().decode(base64String);
                ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
                result = ImageIO.read(stream);
            }
        } catch (Exception e) {
            throw new RuntimeException("Error getting image resource by [" + code + ", " + resource + ", " + pathId + ", " + language + "], Please check whether the resource file or code exists !", e);
        }

        return result;
    }

    @Override
    public ResourceBundle getResourceSet(String metadataId, String pathId, String language) {
        ResourceBundle result = null;
        if (StringUtils.isNotEmpty(metadataId)) {
            language = getLanguage(language);
            try {
                result = getResourceSetByMetadataID(metadataId, pathId, language);
            } catch (Exception e) {
                throw new RuntimeException("Error getting ResourceSet by [" + metadataId + ", " + pathId + ", " + language + "], Please check whether the resource file or code exists !", e);
            }
        }

        return result;
    }

    /**
     * 根据资源编号返回默认语言下的资源信息
     */
    private String getStringByResourceID(String code, String resource, String pathId, String language) {
        //获取code对应的value
        String value = "";
        ResourceBundle bundle = getResourceBundle(pathId, resource, language);
        if (bundle != null) {
            try {
                value = bundle.getString(code);
            } catch (MissingResourceException e) {
                //找到资源文件，但是资源文件中没有资源的报错异常
            }
        }

        return value;
    }

    /**
     * 根据资源编号返回默认语言下的资源信息
     */
    private byte[] getImageByResourceID(String code, String resource, String pathId, String language) {
        //获取code对应的value
        byte[] value = null;
        ResourceBundle bundle = getResourceBundle(pathId, resource, language);
        if (bundle != null) {
            try {
                value = bundle.getString(code).getBytes(StandardCharsets.UTF_8);
            } catch (MissingResourceException e) {
                //找到资源文件，但是资源文件中没有资源的报错异常
            }
        }

        return value;
    }

    /**
     * 根据资源元数据id、su、language获取对应资源集
     */
    private ResourceBundle getResourceSetByMetadataID(String metadataId, String pathId, String language) {
        return getResourceBundle(pathId, metadataId, language);
    }

    private ResourceBundle getResourceBundle(String pathId, String resource, String language) {
        ResourceBundle bundle = null;
        if (resolver != null) {
            bundle = resolver.getResource(pathId, resource, language);
        }

        return bundle;
    }

    //获取languge
    private String getLanguage(String language) {
        return StringUtils.isEmpty(language) ? I18nContext.current.getLanguage() : language;
    }

}
